#include "socket_base.h"

//socket地址类构造函数
CSktAddr::CSktAddr() : fd(INVALIDFD), ip(), port(0)
{
}

//返回 ip地址:端口号:socket 格式的字符串
STRCPP CSktAddr::addr()
{
	OSTREAM addr;
	addr << ip << ":" << port << ":" << fd;
	return addr.str();
}

STRCPP CSktAddr::portstr()
{
	SSTREAM pstr;
	pstr << port;
	return pstr.str();
}


//设置socket为非阻塞
VOID CSktAddr::set_noblock()
{
	fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
}


//设置socket地址各个字段
VOID CSktAddr::setaddr(SOCKFD sfd, STRCPP sip, WORD16 sport)
{
	fd    = sfd;
	ip    = sip;
	port  = sport;
}

CSktReq::CSktReq() : local_addr_(), peer_addr_()
{
}

CSktReq::~CSktReq()
{
}

//关闭套接字
VOID CSktReq::closefd(SOCKFD fd)
{
    if(INVALIDFD != fd)
    {
        close(fd);
        fd = INVALIDFD;
    }
}

VOID CSktReq::closeself()
{
    closefd(local_addr_.fd);
}

VOID CSktReq::closepeer()
{
    closefd(peer_addr_.fd);
}

VOID CSktReq::set_local_addr(SOCKFD fd)
{
	SOCKADDRIN addr = {0};
	WORD32     size = sizeof(addr);
	getsockname(fd, (SOCKADDR*)&addr, &size);
    local_addr_.fd   = fd;
    local_addr_.ip   = inet_ntoa(addr.sin_addr);
    local_addr_.port = ntohs(addr.sin_port);
}

VOID CSktReq::set_peer_addr(SOCKFD fd)
{
	SOCKADDRIN addr = {0};
	WORD32     size = sizeof(addr);
	getpeername(fd, (SOCKADDR*)&addr, &size);
    peer_addr_.fd   = fd;
    peer_addr_.ip   = inet_ntoa(addr.sin_addr);
    peer_addr_.port = ntohs(addr.sin_port);
}

BOOL CSktReq::readinfo(STRCPP& info)
{
    CHAR    tmp[16 * 1024] = {0};
    SWORD32 len = 0;

    len = recv(peer_addr_.fd, tmp, sizeof(tmp), 0);
    if(0 < len)
    {
        info.clear();
        info.append(tmp, len);
        return TRUE;
    }
    if(0 == len)
    {
        //cout << "---recv falied connect closed: " << peer_addr_.addr() << endl;
        closepeer();
        return FALSE;
    }
    else
    {
        if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
        {
            return TRUE;
        }
        //cout << "recv falied connect closed: "<<peer_addr_.addr()<<"errno:"<<errno<<endl;
        closepeer();
        return FALSE;
    }
}

BOOL CSktReq::sendinfo(const STRCPP& info)
{
    WORD32  sendLen = 0;
    SWORD32 tempLen = 0;
    const CHAR*  buffer = info.c_str();
    const WORD32 size   = info.size();

    if(NULL == buffer)
    {
        return FALSE;
    }
    while(sendLen < size)
    {
        tempLen = send(peer_addr_.fd, buffer+sendLen, size-sendLen, MSG_NOSIGNAL);
        if(-1 == tempLen)
        {
            if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
            {
                continue;
            }
            cout<<"send errno: "<<errno<<"socket: "<<peer_addr_.fd<<"content:"<<buffer<<endl;
            return FALSE;
        }
        else
        {
            sendLen += tempLen;
        }
    }
    return TRUE;
}

CSktApp::~CSktApp()
{
	if(NULL != m_reqtype)
	{
		m_reqtype->closeself();
        m_reqtype->closepeer();
		delete m_reqtype;
		m_reqtype = NULL;
	}
}

VOID CSktApp::setreq(CSktReq* reqtype)
{
    if(NULL != m_reqtype)
    {
        delete m_reqtype;
    }
    m_reqtype = reqtype;
}

VOID CSktApp::startup()
{
    if(NULL != m_reqtype)
    {
        //printf("......1\n");
        if(m_reqtype->initialize(m_ip, m_port, m_reqblock))
        {
            working();  // working必须有个循环在一直执行
        }
        //printf(".......2\n");
    }
    else
    {
        cout << "CSktApp startup failed." << endl;
    }
}

STRCPP get_current_time()
{
	TIMET   tt = time(NULL);
	TIMETM* t  = localtime(&tt);
	CHAR    str[100] = {0};

	sprintf(str, "%d-%02d-%02d %02d:%02d:%02d",
		    t->tm_year + 1900,
		    t->tm_mon + 1,
		    t->tm_mday,
		    t->tm_hour,
		    t->tm_min,
		    t->tm_sec);
	return str;
}

STRCPP getgmttime(TIMET timestamp)
{
	static const CHAR* NAME_WEEKDAY[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
	static const CHAR* NAME_MONTH[]   = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
									      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
	CHAR    str[100] = {0};
	TIMETM* timegmt;									      
	timegmt = gmtime(&timestamp);

	sprintf(str, "%s, %02d %3s %4d %02d:%02d:%02d GMT",
		    NAME_WEEKDAY[timegmt->tm_wday],
		    timegmt->tm_mday,
		    NAME_MONTH[timegmt->tm_mon],
		    timegmt->tm_year + 1900,
		    timegmt->tm_hour,
		    timegmt->tm_min,
		    timegmt->tm_sec);
	return STRCPP(str);								      
}

/* 从buffer中读取一行 \n或\r\n 并且去掉了\n 或\r\n */
BOOL getline(STRCPP& buffer, STRCPP& line)
{
	ULONG linepos = buffer.find('\n');
	if(string::npos == linepos)
	{
		return FALSE;
	}
	line.clear();
	if(linepos > 0 && buffer[linepos-1] == '\r')
	{
		line.assign(buffer, 0, linepos-1);
	}
	else
	{
		line.assign(buffer, 0, linepos);
	}
	buffer.erase(0, linepos+1);
	return TRUE;
}

/* 从buffer中读取前size个字节 放入str 并从buffer中删除前size个字节 */
BOOL getsize(STRCPP& buffer, STRCPP& str, ULONG size)
{
	str.clear();
	if(buffer.size() < size)
	{
		return FALSE;
	}
	str.assign(buffer, 0 , size);
	buffer.erase(0, size);
	return TRUE;
}


/* 从buffer中删除末尾的 \n或\r\n */
VOID del_crlf(STRCPP& buffer)
{
	ULONG size = buffer.size();

	if(0 < size && '\n' == buffer[size-1])
	{
		size--;
		if(0 < size && '\r' == buffer[size-1])
		{
			size--;
		}
		buffer.assign(buffer, 0, size);
	}
}

/* 以sep分割str 放入strvec中 
   strvec.size() 肯定 >= 1
   如果sep位于str的开始或结尾 则strvec的第一个或最后一个为空字符串 */
VOID strsplit(const STRCPP& str, STRCPP sep, STRVEC& strvec)
{
	ULONG  pos1 = 0;
	ULONG  pos2 = 0;
	STRCPP strtmp;
	strvec.clear();

	pos2 = str.find(sep);
	while(string::npos != pos2)
	{
		strtmp = str.substr(pos1, pos2 - pos1);
		//if(0 != strtmp.size())
		//{
			strvec.push_back(strtmp);
		//}
		pos1 = pos2 + sep.size();
		pos2 = str.find(sep, pos1);
	}
	strtmp = str.substr(pos1);
	//if(0 != strtmp.size())
	//{
		strvec.push_back(strtmp);
	//}
}


